package bgpv1

import (
	"fmt"
	"strings"
	"topobuild/base"
	"topobuild/simu"
)

type BgpV1 struct {
	tb_BGPv1Node    []TableBGPv1Node
	tb_BGPv1Nei     []TableBGPv1Nei
	tb_BGPv1Unicast []TableBGPv1Unicast
}

func NewBgpV1() *BgpV1 {
	return &BgpV1{}
}

func (bgp *BgpV1) GenTableRoute(sk *simu.SimuKeeper, conf *base.Config, outfile string) {
	rlist := make([]TableBGPv1Rm, 0)
	WriteRmXlsx(outfile, rlist)
}

func (bgp *BgpV1) GenTableUnicast(sk *simu.SimuKeeper, conf *base.Config, outfile string) {

	delMask24End := func(ip string) string {
		if strings.HasSuffix(ip, "/24") {
			return strings.TrimSuffix(ip, "/24")
		}
		return ip
	}

	uniList := make([]TableBGPv1Unicast, 0)
	for _, aa := range conf.AsAreas {
		if aa.As <= 0 {
			continue
		}
		localAS := aa.As
		for _, dia := range aa.DevInAs {
			// 检查设备的所有对端设备
			for _, id := range dia.Intfs {
				peerDev, peerPortIp := conf.FindPeerDev(dia.Dev, id.Port, id.PortIp)
				if peerDev == "" {
					continue
				}
				peerAS := conf.GetDevAs(peerDev)
				if peerAS <= 0 {
					continue
				}
				if peerAS == localAS {
					continue
				}
				// fmt.Printf("peerAS's AS : %d\n", peerAS)
				tbgp := &TableBGPv1Unicast{
					DevName: dia.Dev,
					As:      localAS,
					Net:     "",
					NeiAs:   peerAS,
					NeiIp:   delMask24End(peerPortIp),
				}
				uniList = append(uniList, *tbgp)
			}
		}
	}

	// 保存一些必要的信息
	bgp.tb_BGPv1Unicast = uniList
	WriteUnicastXlsx(outfile, uniList)
}

func (bgp *BgpV1) GenTableNeighbor(sk *simu.SimuKeeper, conf *base.Config, outfile string) {
	neiList := make([]TableBGPv1Nei, 0)
	for _, aa := range conf.AsAreas {
		if aa.As <= 0 {
			continue
		}
		localAS := aa.As
		for _, dia := range aa.DevInAs {
			// 检查是否需要启动RR
			needRR := false
			subNeiList_sameAS := make([]TableBGPv1Nei, 0)
			// subNeiList_nosaAS := make([]TableBGPv1Nei, 0)
			// 检查设备的所有对端设备
			for _, id := range dia.Intfs {
				peerDev, _ := conf.FindPeerDev(dia.Dev, id.Port, id.PortIp)
				if peerDev == "" {
					continue
				}
				// fmt.Printf("found peerDev : %s\n", peerDev)
				peerAS := conf.GetDevAs(peerDev)
				if peerAS <= 0 {
					continue
				}
				// fmt.Printf("peerAS's AS : %d\n", peerAS)
				peerLoopback0Ip := conf.GetDevLoopBack0Ip(peerDev)
				tbgp := &TableBGPv1Nei{
					DevName:  dia.Dev,
					NeiId:    peerLoopback0Ip,
					NeiAs:    peerAS,
					Vpn:      "否",
					EnableRR: "否",
				}
				fmt.Printf("key = %s - %s\n", tbgp.DevName, tbgp.NeiId)
				if localAS == peerAS {
					subNeiList_sameAS = append(subNeiList_sameAS, *tbgp)
				} else {
					fmt.Printf("needRR localAS : %d, peerAS : %d\n", localAS, peerAS)
					needRR = true // EBGP路由器需要启动RR
					// subNeiList_nosaAS = append(subNeiList_nosaAS, *tbgp)
				}
			}
			// 启动对AS内的RR
			if needRR {
				for i := range subNeiList_sameAS {
					subNeiList_sameAS[i].EnableRR = "是"
				}
			}
			// 放入总列表
			neiList = append(neiList, subNeiList_sameAS...)
			// TODO: AS不同的需要配置unicast子表
			// neiList = append(neiList, subNeiList_nosaAS...)
		}
	}

	// 保存一些必要的信息
	bgp.tb_BGPv1Nei = neiList
	WriteNeiXlsx(outfile, neiList)
}

func (bgp *BgpV1) GenTableNode(sk *simu.SimuKeeper, conf *base.Config, outfile string) {
	nodelist := make([]TableBGPv1Node, 0)
	for _, aa := range conf.AsAreas {
		if aa.As <= 0 {
			continue
		}
		for _, dia := range aa.DevInAs {
			// 获取设备id
			devName := dia.Dev
			devId := conf.GetDevLoopBack0Ip(devName)
			asNum := conf.GetDevAs(devName)
			nodelist = append(nodelist, TableBGPv1Node{
				DevName: devName,
				DevId:   devId,
				As:      asNum,
			})
		}
	}

	// 保存一些必要的信息
	bgp.tb_BGPv1Node = nodelist
	WriteNodeXlsx(outfile, nodelist)
}
